<?php

namespace app\common\library;

use alipay\aop\AopClient;
use alipay\aop\request\AlipayTradeAppPayRequest;
use app\common\controller\Api;
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Util\Signer;
use app\common\model\MoneyLog;
use app\common\model\order\Order;
use app\common\model\User;
use EasyWeChatComposer\EasyWeChat;
use think\Db;
use think\Env;
use think\Log;
use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
use WeChatPay\Util\PemUtil;
use wechatPay\Wxpay;

/**
 * 统一支付接口
 */
class Pay extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];
    public function __construct()
    {
    }
    /**
     * 余额支付
     *
     */
    public static function yue($data, $payPwd)
    {
        $user = User::get($data['user_id']);

        if ($user->pay_pwd != md5(md5($payPwd) . 'pcy')) {
            exception('支付密码不正确');
        }

        $totalMoney = bcadd($user->money, $user->no_money, 2);
        if ($data['pay_money'] > $totalMoney) {
            exception('余额不足');
        }
        Db::startTrans();
        try {
            if ($user->no_money > $data['pay_money']) {
                MoneyLog::income($user->id, $data['pay_money'], 1, 503, $data['sn']);
            } else {
                if ($user->no_money > 0) {
                    $money = bcsub($data['pay_money'], $user->no_money, 2);
                    MoneyLog::income($user->id, $user->no_money, 1, 503, $data['sn']);
                } else {
                    $money = $data['pay_money'];
                }
                if ($money > 0) {
                    MoneyLog::income($user->id, $money, 1, 504, $data['sn']);
                }
            }

            self::orderFulfillment($data['sn'], 3);
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            return $e->getMessage();
        }
        return true;
    }
    /**
     * 支付宝支付
     *
     */
    public static function alipay($data)
    {
        if (Env::get('app.debug') == true) {
            $data['pay_money'] = 0.01;
        }
        $aop = new AopClient();
        $object['out_trade_no'] = $data['sn'];
        $object['total_amount'] = $data['pay_money'];
        $object['subject'] = $data['title'];
        $json = json_encode($object);
        $request = new AlipayTradeAppPayRequest();
        $request->setNotifyUrl(cdnurl('/api/notify/alipayNotify', true));
        $request->setBizContent($json);
        $result = $aop->sdkExecute($request);
        return $result;
    }
    public static function wechatArousePay($order_info)
    {
        // if (!$order_info) {
        //     return self::fail('该项目不存在或已支付');
        // }
        // if ($order_info['pay_money'] <= 0) {
        //     return self::fail('订单支付金额不合法！');
        // }
        $PaymentAmount = bcmul($order_info['pay_money'], 100, 0);
        // 商户号，假定为`1000100`
        $merchantId = config('site.mch_id');

        // 商户私钥，文件路径假定为 `/path/to/merchant/apiclient_key.pem`
        // 这里是微信商户端生成的私钥将整个文件放在wechatpay文件夹下
        $merchantPrivateKeyFilePath = ROOT_PATH  . str_replace('/', DS, substr('/application/certs/apiclient_key.pem', 1));
        // 加载商户私钥
        $merchantPrivateKeyInstance = PemUtil::loadPrivateKey($merchantPrivateKeyFilePath);
        // 商户证书，文件路径假定为 `/path/to/merchant/apiclient_cert.pem`
        // 这里是微信商户端生成的公钥将整个文件放在wechatpay文件夹下
        $merchantCertificateFilePath = ROOT_PATH  . str_replace('/', DS, substr('/application/certs/apiclient_cert.pem', 1));
        // 加载商户证书
        $merchantCertificateInstance = PemUtil::loadCertificate($merchantCertificateFilePath);
        // 解析商户证书序列号
        $merchantCertificateSerial = PemUtil::parseCertificateSerialNo($merchantCertificateInstance);
        // 平台证书，可由下载器 `./bin/CertificateDownloader.php` 生成并假定保存为 `/path/to/wechatpay/cert.pem`
        // php -f ./bin/CertificateDownloader.php -- -k 'WYa96C3GM2PLVt4opEhKwJdez59043qn' -m '1636401539' -f /www/wwwroot/1214pincanyuan.ciyuantiaoyue.com/application/certs/apiclient_key.pem -s 5103D041F1288AB6C72EAB5864EC45D104DD06BB -o /www/wwwroot/1214pincanyuan.ciyuantiaoyue.com/application/certs/certs
        $platformCertificateFilePath =  ROOT_PATH  . str_replace('/', DS, substr('/application/certs/wechatpay.pem', 1));
        // 加载平台证书
        $platformCertificateInstance = PemUtil::loadCertificate($platformCertificateFilePath);
        // 解析平台证书序列号
        $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateInstance);
        // 工厂方法构造一个实例
        $instance = Builder::factory([
            'mchid'      => $merchantId,
            'serial'     => $merchantCertificateSerial,
            'privateKey' => $merchantPrivateKeyInstance,
            'certs'      => [
                $platformCertificateSerial => $platformCertificateInstance,
            ],
        ]);
        try {
            $resp = $instance
                ->v3->pay->transactions->app
                ->post(['json' => [
                    'appid'        => config('site.app_id'),
                    'mchid'        => $merchantId,
                    'description'  => '商品描述',
                    'out_trade_no' => $order_info['sn'],
                    'notify_url'   =>  cdnurl(config('site.notify_url'), true),
                    'amount'       => [
                        'total'    => (int)$PaymentAmount,
                        'currency' => 'CNY'
                    ],
                ]]);
            $result_code = $resp->getStatusCode();
            if ($result_code == 200) {
                $result_data         = json_decode($resp->getBody(), true);
                $arouse_data         = [
                    'appid'     => config('site.app_id'),
                    'timestamp' => time(),
                    'noncestr'  => Wxpay::getNonceStr(),
                    'prepayid'  => $result_data['prepay_id'],
                ];

                $arouse_data['sign'] = Rsa::sign(
                    Formatter::joinedByLineFeed(...array_values($arouse_data)),
                    $merchantPrivateKeyInstance
                );
                $arouse_data['partnerid'] = $merchantId;
                $arouse_data['package'] = "Sign=WXPay";
                return $arouse_data;
            }
        } catch (\Exception $exception) {
            // 进行错误处理
            if ($exception instanceof \GuzzleHttp\Exception\RequestException && $exception->hasResponse()) {
                $r = $exception->getResponse();
                return [$r->getStatusCode(), $r->getReasonPhrase()];
            }
        }
    }

    //微信app支付
    public static function wxpay($order,  $attach)
    {
        $out_trade_no = $order['sn'];
        $money = $order['pay_money'];
        if (Env::get('app.debug') == true) {
            $money = 0.01;
        }
        if (empty($out_trade_no)) return json(['code' => 202, 'msg' => '缺少参数order_sn']);
        // 官方提供网址
        $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/app";
        $urlarr = parse_url($url); //拆解为：[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native]
        $time = time(); //时间戳
        $noncestr = Wxpay::getNonceStr();
        $appid = config('site.app_id'); //appID
        $mchid = config('site.mch_id'); //商户ID
        $xlid =  config('site.serial_no'); //证书序列号
        $data = array();
        $data['appid'] = $appid;
        $data['mchid'] = $mchid;
        $data['attach'] = $attach;
        $data['description'] = '商品描述'; //商品描述
        $data['out_trade_no'] = $out_trade_no; //订单编号，订单号在微信支付里是唯一的
        $data['notify_url'] =  cdnurl('/api/notify/wechatNotify', true); //需根据自己的情况修改回调接口，也可以为空
        $data['amount']['total'] = $money * 100; //金额 单位 分
        $data['scene_info']['payer_client_ip'] = $_SERVER["REMOTE_ADDR"];; //场景ip
        // $data['payer']['openid'] = $openid; //app支付不需要openid
        $data = json_encode($data);
        Log::write($data);

        //签名，包含了$data数据、微信指定地址、随机数和时间
        $key = Wxpay::getSign($data, $urlarr['path'], $noncestr, $time);
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $noncestr, $time, $key);
        //头部信息
        $header  = array(
            'Accept: application/json',
            'Content-Type: application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        );
        //向微信接口地址提交json格式的$data和header的头部信息，得到返回值
        $res = Wxpay::curl_post_https($url, $data, $header);
        $prepay_id = json_decode($res, true)['prepay_id'];


        $paySign = Wxpay::getWechartSign($appid, $time, $noncestr, $prepay_id);
        $payData = [
            'appid' => $appid,
            'partnerid' => $mchid,
            'prepayid' => $prepay_id,
            'package' => "Sign=WXPay",
            'noncestr' => $noncestr,
            'timestamp' => (string) $time,
            'sign' => $paySign
        ];
        return $payData;
    }

    //订单支付成功
    public static function orderFulfillment($sn, $pay_type, $trade_no = null)
    {
        $order = Order::get([
            'status' => 0,
            'sn' => $sn,
        ]);
        if (!$order) {
            exception('订单不存在');
        }
        $user = User::get($order->user_id);

        $total_money = bcadd($user->consumption, $order->pay_money, 2);
        $data['status'] = 1;
        if ($order->distribution == '2') {
            $data['status'] = 2;
            $data['qh_image'] = build($order->id);
        }
        $order['transaction_id'] = $trade_no;
        $data['pay_type'] = $pay_type;
        $data['paytime'] = time();
        $order->save($data);
        $money = $order->pay_money - $order->freight;
        //订单分佣
        MoneyLog::subcommission($money, $user->id, $sn);
        //根据消费额度升级代理等级
        User::nextGroup($total_money, $user->id);
        //升级星级用户
        if ($user->paren_ids) {
            User::starUpgrade($user->paren_ids);
        }
    }
}
